package com.github.dongglin.smart.spring.boot.plus.core.framework.exception;

import com.github.dongglin.smart.spring.boot.plus.common.exception.BusinessException;
import com.github.dongglin.smart.spring.boot.plus.core.framework.response.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
@SuppressWarnings({"DuplicatedCode", "unused"})
public class GlobalExceptionHandler {
    /**
     * 类属性参数校验异常处理
     *
     * @param e e
     * @return ApiResponse
     */
    @ExceptionHandler(value = {BindException.class, MethodArgumentNotValidException.class})
    @ResponseBody
    public ApiResponse<Object> methodArgumentNotValidException(Exception e) {
        String allErrorMsg = "请求参数格式错误";
        String errorMsg = "请求参数格式错误";
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = ((MethodArgumentNotValidException) e);
            allErrorMsg = exception.getBindingResult().getFieldErrors().stream()
                    .map(a -> a.getObjectName() + "-" + a.getField() + "-" + a.getDefaultMessage())
                    .collect(Collectors.joining("\n"));
            errorMsg = Objects.requireNonNull(exception.getBindingResult().getFieldError()).getDefaultMessage();
        } else {
            BindException exception = ((BindException) e);
            allErrorMsg = exception.getBindingResult().getFieldErrors()
                    .stream()
                    .map(a -> a.getObjectName() + "-" + a.getField() + "-" + a.getDefaultMessage())
                    .collect(Collectors.joining("\n"));
            errorMsg = Objects.requireNonNull(exception.getBindingResult().getFieldError()).getDefaultMessage();
        }
        return ApiResponse.failure(errorMsg);
    }

    /**
     * @param e e
     * @return ApiResponse
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseBody
    public ApiResponse<Object> httpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        log.error("不支持到请求方式", e);
        return ApiResponse.failure("");
    }

    /**
     * 全局非字段验证类错误
     *
     * @param e 异常信息
     * @return 对异常信息的统一处理返回信息
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public ApiResponse<Object> handleBizException(BusinessException e) {
        return ApiResponse.failure(e.getCode(), e.getMessage(), "");
    }

    /**
     * @param e e
     * @return 处理全局异常
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ApiResponse<Object> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return ApiResponse.failure(e.getMessage());
    }
}
